import logging

from flask import abort
from flask import g
from flask import render_template, current_app, jsonify
from flask import request

from info import constants, db
from info.models import User, Category, News, Comment, CommentLike
from info.utils.common import user_login_data
from info.utils.response_code import RET
from . import news_blue


@news_blue.route('/comment_like', methods=["POST"])
@user_login_data
def set_comment_like():
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    # 获取参数
    comment_id = request.json.get('comment_id')
    action = request.json.get('action')
    # 参数校验
    if not all([comment_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    if action not in ["add", "remove"]:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 查询该条评论的信息
    try:
        comment = Comment.query.get(comment_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
        # 从数据库取值，要判断它是否为空
    if not comment:
        return jsonify(errno=RET.NODATA, errmsg='无该评论信息')

    # 判断是否被点赞
    if action == 'add':
        try:
            comment_like = CommentLike.query.filter_by(comment_id=comment_id, user_id=user.id).first()
        except Exception as e:
            logging.error(e)
            return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')

        if not comment_like:
            comment_like = CommentLike()
            comment_like.user_id = user.id
            comment_like.comment_id = comment_id
            db.session.add(comment_like)
            # 点赞数加1
            comment.like_count += 1

    else:
        comment_like = CommentLike.query.filter_by(comment_id=comment_id, user_id=user.id).first()
        if comment_like:
            db.session.delete(comment_like)
            comment.like_count -= 1
    # 提交
    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='提交数据库错误')
    return jsonify(errno=RET.OK, errmsg='点赞成功')


@news_blue.route('/followed_user', methods=["POST"])
@user_login_data
def followed_user():
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登陆')
    # 获取参数
    user_id = request.json.get('user_id')
    action = request.json.get('action')
    # 参数校验
    if not all([user_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    if action not in ["follow", "unfollow"]:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 逻辑处理
    # 查询目标用户
    try:
        target_user = User.query.get(user_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
        # 从数据库取值，要判断它是否为空
    if not target_user:
        return jsonify(errno=RET.NODATA, errmsg='无该用户信息')

    # 根据action的值来进行关注或取关的操作
    if action == 'follow':
        # 判断目标用户的粉丝中是否有当前用户
        if target_user.followers.filter(User.id == user.id).count() > 0:
            return jsonify(errno=RET.PARAMERR, errmsg='该用户已关注过')
        target_user.followers.append(user)
    else:
        if target_user.followers.filter(User.id == user.id).count() > 0:
            target_user.followers.remove(user)

    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='数据库提交失败')
    return jsonify(errno=RET.OK, errmsg='成功')


@news_blue.route('/news_comment', methods=['POST'])
@user_login_data
def news_comment():
    # 一. 获取数据
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登陆')
    json_data = request.json
    news_id = json_data.get('news_id')
    comment_str = json_data.get('comment')
    parent_id = json_data.get('parent_id')
    # 二. 校验参数
    if not all([news_id, comment_str]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数有误')
    # 三. 逻辑处理
    # 从数据库中查询到该条新闻
    try:
        news = News.query.get(news_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询出错')
        # 从数据库取值，要判断它是否为空
    if not news:
        return jsonify(errno=RET.NODATA, errmsg='无该条新闻的信息')

    # 创建评论的模型
    comment = Comment()
    comment.news_id = news_id
    comment.user_id = user.id
    comment.content = comment_str
    if parent_id:
        comment.parent_id = parent_id
    # 提交
    try:
        db.session.add(comment)
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='数据库提交错误')

    # 返回数据
    return jsonify(errno=RET.OK, errmsg='成功', data=comment.to_dict())


@news_blue.route('/news_collect', methods=['POST'])
@user_login_data
def news_collect():
    # 一. 获取参数
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    json_data = request.json
    news_id = json_data.get('news_id')
    action = json_data.get('action')
    # 二. 校验参数
    if not news_id:
        return jsonify(errno=RET.PARAMERR, errmsg='参数有误')
    if action not in ['collect', 'cancel_collect']:
        return jsonify(errno=RET.PARAMERR, errmsg='参数有误')

    # 三. 逻辑处理
    try:
        news = News.query.get(news_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
        # 从数据库取值，要判断它是否为空
    if not news:
        return jsonify(errno=RET.NODATA, errmsg='没有该新闻数据')

    if action == 'collect':
        # 判断该新闻不在用户的收藏列表中才添加收藏
        if news not in user.collection_news:
            user.collection_news.append(news)
    else:
        # 判断该新闻被收藏过才能删除
        if news in user.collection_news:
            user.collection_news.remove(news)
    # 提交
    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='数据库错误')
    # 四. 返回数据
    return jsonify(errno=RET.OK, errmsg='成功')


@news_blue.route('/<news_id>')
@user_login_data
def get_news_details(news_id):
    # 一. 获取当前登录的用户的id
    user = g.user
    # 二. 点击排行显示
    # 从数据库按照点击量降序查询前10条新闻
    try:
        news_click_models = News.query.order_by(News.clicks.desc()).limit(10)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='mysql数据库查询错误')
    # 将模型转换为字典，存入列表中
    click_list = []
    for news in news_click_models if news_click_models else []:
        click_list.append(news.to_basic_dict())

    # 三. 获取新闻详情
    # 3.1 查询新闻信息
    try:
        news = News.query.get(news_id)
    except Exception as e:
        logging.error(e)
        abort(500)
        # 从数据库取值，要判断它是否为空
    if not news:
        abort(404)
    # 3.2 增加点击量
    news.clicks += 1

    # 3.3 提交到数据库中
    try:
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        abort(404)

    # 四. 实现收藏和删除
    # 设置一个标志变量来表示用户是否收藏
    is_collected = False
    # 判断该新闻是否在已登陆用户的收藏列表中，进行相应的操作
    if user:
        if news in user.collection_news:
            is_collected = True
    # 判断当前登陆用户是否关注该新闻作者和并展示该新闻作者的相应信息显示
    is_followed = False
    if user and news.user:
        if user in news.user.followers:
            is_followed = True

    # 五. 实现新闻列表的显示
    # 获取该新闻的评论列表
    comment_models = []
    try:
        comment_models = Comment.query.filter(Comment.news_id == news_id).order_by(Comment.create_time.desc()).all()
    except Exception as e:
        current_app.logger.error(e)
        abort(500)

    # 评论有点赞的id列表
    comment_like_ids = []
    # 得到该新闻的评论的id
    if user:
        try:
            comment_ids = [comment.id for comment in comment_models]
            if len(comment_ids) > 0:
                # 取出所有有点赞记录的评论
                comment_likes = CommentLike.query.filter(CommentLike.comment_id.in_(comment_ids),
                                                         CommentLike.user_id == user.id).all()
                # 得到以上类型评论的id
                comment_like_ids = [comment_like.comment_id for comment_like in comment_likes]
        except Exception as e:
            logging.error(e)
            return jsonify(errno=RET.DBERR, errmsg='查询错误')
    comment_list = []
    for comment in comment_models:
        comment_dict = comment.to_dict()
        comment_dict['is_like'] = False
        if user and comment.id in comment_like_ids:
            comment_dict['is_like'] = True
        comment_list.append(comment_dict)

    data = {
        "user": user.to_dict() if user else None,
        "click_list": click_list,
        "news": news.to_dict() if news else None,
        "is_collected": is_collected,
        "comment_list": comment_list,
        'is_followed': is_followed
    }

    return render_template('news/detail.html', data=data)
